"""
Haiku (PowerSchool Learning) backend

This file is part of polyglot, etc.
"""

from lxml import etree
from lxml.html import parse
from lxml.html import tostring
from lxml.html.clean import Cleaner
from io import StringIO
from .support import Backend, Course, ResourceCategory, ResourceRawHTML, FileUpload, Quiz, MultipleChoiceQuestion, FreeResponseQuestion, Forum, Post
from ..authentication import google as GoogleAuth
import requests
import re

class HaikuForum(Forum):
    def __init__(self, backend, course, discussion, referer):
        self.backend = backend
        self.course = course
        self.discussion = discussion
        self.posts = {}
        self.tmp_key = ""

        anchor = discussion.getparent()
        self.name = anchor.text_content().strip().replace("Discuss: ", "") + "F"
        
        (discussion_id, page_id) = anchor.attrib["onclick"][len("dscView("):-len(")")].split(",")
        self.id = discussion_id
        self.page_id = page_id

        self.referer = referer

    def extract_post(self, div, children):
        name = div.cssselect(".name")[0].text_content().strip()
        date = div.cssselect(".detail")[0].text_content().strip()
        subject = div.cssselect(".subject")[0].text_content().strip()
        body = div.cssselect(".body")[0].text_content().strip()
        id = div.attrib["id"][len("dsc_post"):]

        return Post(id, name, body, children)

    @property
    def thread(self):
        url = self.backend.base + self.course.id + "/discussion/view2/" + self.id 
        inner_tree = self.backend.fake_xhr("GET", url, {
            "group_id": "",
            "page_id": self.page_id,
            "thread_id": "",
            "user_id": ""
        }, self.referer)

        dt = inner_tree.cssselect("#dsc_detail")[0]
        etree.strip_elements(dt, "script")
        detail = dt.text_content().strip()

        threads = []
        posts = []

        t_url = self.backend.base + self.course.id + "/discussion/thread_posts/" + self.id
        
        for thread in inner_tree.cssselect(".thread_item"):
           thread_id = thread.attrib["id"][len("thread_item"):]

           ft = self.backend.fake_xhr("POST", t_url, {
                   "csrf_token": self.backend.csrftok,
                   "thread_id": thread_id
            }, self.referer)

           self.tmp_key = ft.cssselect("#tb_tmp_key")[0].attrib["value"]

           replies = [self.extract_post(post, []) for post in ft.cssselect(".dsc_post:not(.dsc_top_post)")]
           top = self.extract_post(ft.cssselect(".dsc_top_post")[0], replies)
           threads += [top]
           posts += [top]
           posts += replies

        root = Post("root-" + self.id, "Instructor", detail, threads)
        posts += [root]
        self.flush_posts(posts)

        return root

    def reply(self, parent, body):
        params = {
               "csrf_token": self.backend.csrftok,
               "tmp_key": self.tmp_key,
               "dsc_v2": 1,
               "plain_text": 1, # TODO: HTML
               "post[replyto_post_id]": parent.id if parent else "",
               "post[subject]": "",
               "post[body]": body
        }

        url = self.backend.base + self.course.id + "/post/create/" + self.id
        self.backend.fake_xhr("POST", url, params, self.referer)

        return True # TODO

class HaikuResourceXHR(ResourceCategory):
    def __init__(self, name, b_id, backend, course, referer):
        self.b_id = b_id
        self.backend = backend
        self.course = course
        self.referer = referer

        self.name = name
        self.forums = []

        self.html = ResourceRawHTML(name, self.get_html())

    @property
    def children(self):
        return [self.html] + self.forums

    def find_discussion(self, tree):
        for discussion in tree.cssselect("i.icon-discussion"):
            self.forums += [HaikuForum(self.backend, self.course, discussion, self.referer)]

    def get_html(self):
        url = self.backend.base + self.course.id + "/cms_box/render_content/" + self.b_id

        tree = self.backend.fake_xhr("POST", url,  {"csrf_token": self.backend.csrftok}, self.referer)
        self.find_discussion(tree)

        cleaner = Cleaner()
        cleaner.javascript = True
        tree = cleaner.clean_html(tree)

        tag = []

        for link in tree.cssselect("a"):
            print(link)
            if "href" in link.attrib:
                href = link.attrib["href"]
                print(href)
                parts = href.split("/")
                print(parts)
                
                if parts[0] == "":
                    if len(parts) >= 5 and parts[3] == "assignment" and parts[4] == "view":
                        tag += [cleaner.clean_html(self.backend.fake_xhr("GET", self.backend.base + href, {}, self.referer))]
                    else:
                        link.attrib["href"] = self.backend.base + href

        print(tag)
        return "".join([tostring(t).decode("utf-8") for t in ([tree] + tag)])

class HaikuResourceCategory(ResourceCategory):
    def __init__(self, name, url, base_children, backend, course):
        self.name = name
        self.url = url
        self.base_children = base_children
        self.backend = backend
        self.course = course

    @property
    def children(self):
        ret = self.base_children

        out = self.backend.session.get(self.backend.base + self.url)
        tree = parse(StringIO(out.text)).getroot()
        for box in tree.cssselect(".cms_box"):
            name = box.text_content().strip()
            b_id = box.get("id")[len("box_"):]

            ret += [HaikuResourceXHR(name, b_id, self.backend, self.course, self.backend.base + self.url)]

        return ret

"""
class HaikuQuiz(Quiz):
    def __init__(self, course, id, name):
        super().__init__(id, name)
        self.course = course

    def questions(self):
        question1 = MultipleChoiceQuestion("Is mathematics fun?", ["Absolutely!", "Definitely!"])
        question2 = FreeResponseQuestion("What's your favourite part?")

        return [question1, question2]

    def submit(self, responses):
        return True
"""

class HaikuCourse(Course):
    def __init__(self, backend, course):
        self.backend = backend

        # onclick ala redirect_to('/teacher/coursestring/cms_page/view')
        # why they can't just use an <a> is a mystery o_o

        self.url = course.get("onclick")[len("redirect_to('"):-(len("')"))]
        self.id = self.url[:-len("/cms_page/view")]

        # Course name and teacher name, no localisation?
        self.title = course.text_content().strip()
        self.teacher = "Unknown teacher" # TODO?

        self.grade_summary = None

    def course_page(self):
        return parse(StringIO(self.backend.session.get(self.backend.base + self.url).text)).getroot()

    """
    There are a *lot* of resources Haiku emits.
    The most basic are found in the sidebar (#sidebar)
    Take the links and interpret them semantically based on list tags (reasonable HTML, huh?!)
    Deeper nested resources are more links away (and XHR); careful about bandwidth!
    """

    @property
    def resources(self):
        def process_li(li):
            name = ""
            href = ""
            children = []

            for child in li:
                if child.tag == "div":
                    link = child.cssselect("a")[0]
                    name = link.text_content().strip()
                    href = link.get("href")
                elif child.tag == "ul":
                    children = [process_li(li) for li in child]

            return HaikuResourceCategory(name, href, children, self.backend, self)

        sidebar = self.course_page().cssselect("#sidebar")[0][0]
        return [process_li(li) for li in sidebar]

class HaikuBackend(Backend):
    Config = ["Email", "Password", "School"]

    def login(self, config):
        self.base = "https://" + config["School"] + ".learning.powerschool.com"

        endpoint = self.base + "/do/authentication/google/google_begin?&openid_identifier=" + config["Email"].split("@")[1]
        out = GoogleAuth.auth(self.session, config, endpoint)

        self.portal = parse(StringIO(out.text))
        print(out.text)
        self.csrftok = re.search("^  CSRFTOK = '([0-9a-f]*)';$", out.text, re.MULTILINE).group(1)

        return True # TODO

    def fake_xhr(self, method, url, data, referer):
        headers = {
            "X-Requested-With": "XMLHttpRequest",
            "X-Prototype-Version": "1.7",
            "Referer": referer
        }

        if method == "GET":
            s = self.session.get(url, params=data, headers=headers)
        else:
            s = self.session.post(url, data, headers=headers)

        return parse(StringIO(s.text)).getroot()

    def fast_login(self, config):
        self.base = "https://" + config["School"] + ".learning.powerschool.com"

        username = config["Email"].split("@")[0]
        p = self.session.get(self.base + "/u/" + username + "/portal")
        self.portal = parse(StringIO(p.text))
        self.csrftok = re.search("^  CSRFTOK = '([0-9a-f]*)';$", p.text, re.MULTILINE).group(1)

    @property
    def courses(self):
        courses = []

        for course in self.portal.getroot().cssselect(".filter-class"):
            courses += [HaikuCourse(self, course)]

        return courses
